#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>

void handleErrors() {
    ERR_print_errors_fp(stderr);
    abort();
}

// 生成 RSA 密钥对并导出到文件
void generate_RSA_keypair(const char *public_path, const char *private_path) {
    RSA *rsa = NULL;
    BIGNUM *bn = BN_new();
    int ret;

    // 初始化 BIGNUM 以设置公钥指数
    if (BN_set_word(bn, RSA_F4) != 1)
        handleErrors();

    // 生成 RSA 密钥
    rsa = RSA_new();
    ret = RSA_generate_key_ex(rsa, 2048, bn, NULL); // 2048-bit 密钥
    if (ret != 1)
        handleErrors();

    // 导出公钥
    FILE *pub_file = fopen(public_path, "wb");
    PEM_write_RSAPublicKey(pub_file, rsa);
    fclose(pub_file);

    // 导出私钥
    FILE *priv_file = fopen(private_path, "wb");
    PEM_write_RSAPrivateKey(priv_file, rsa, NULL, NULL, 0, NULL, NULL);
    fclose(priv_file);

    // 清理
    RSA_free(rsa);
    BN_free(bn);
}

// 使用公钥进行加密
int rsa_encrypt(const char *public_path, const unsigned char *plaintext, unsigned char *ciphertext) {
    RSA *rsa = NULL;
    FILE *pub_file = fopen(public_path, "rb");
    if (!pub_file) {
        fprintf(stderr, "Unable to open public key file.\n");
        return -1;
    }

    // 读取公钥
    rsa = PEM_read_RSAPublicKey(pub_file, NULL, NULL, NULL);
    fclose(pub_file);

    if (!rsa) {
        fprintf(stderr, "Unable to read public key.\n");
        return -1;
    }

    int result = RSA_public_encrypt(strlen((const char *)plaintext), plaintext, ciphertext, rsa, RSA_PKCS1_PADDING);

    RSA_free(rsa);
    return result; // 返回加密结果长度
}

// 使用私钥进行解密
int rsa_decrypt(const char *private_path, const unsigned char *ciphertext, unsigned char *plaintext) {
    RSA *rsa = NULL;
    FILE *priv_file = fopen(private_path, "rb");
    if (!priv_file) {
        fprintf(stderr, "Unable to open private key file.\n");
        return -1;
    }

    // 读取私钥
    rsa = PEM_read_RSAPrivateKey(priv_file, NULL, NULL, NULL);
    fclose(priv_file);

    if (!rsa) {
        fprintf(stderr, "Unable to read private key.\n");
        return -1;
    }

    int result = RSA_private_decrypt(RSA_size(rsa), ciphertext, plaintext, rsa, RSA_PKCS1_PADDING);

    RSA_free(rsa);
    return result; // 返回解密结果长度
}

int main() {
    const char *public_key_path = "public.pem";
    const char *private_key_path = "private.pem";
    unsigned char plaintext[256] = "Hello, RSA!";
    unsigned char ciphertext[256];
    unsigned char decryptedtext[256];

    // 生成 RSA 密钥对
    generate_RSA_keypair(public_key_path, private_key_path);

    // 打印原始明文
    printf("Plaintext: %s\n", plaintext);

    // 进行加密
    int ciphertext_len = rsa_encrypt(public_key_path, plaintext, ciphertext);
    if (ciphertext_len == -1) {
        fprintf(stderr, "Encryption failed.\n");
        return 1;
    }
    printf("Ciphertext (in hex): ");
    for (int i = 0; i < ciphertext_len; i++) {
        printf("%02x", ciphertext[i]); // 打印加密后的密文，十六进制格式
    }
    printf("\n");

    // 进行解密
    int decryptedtext_len = rsa_decrypt(private_key_path, ciphertext, decryptedtext);
    if (decryptedtext_len == -1) {
        fprintf(stderr, "Decryption failed.\n");
        return 1;
    }
    decryptedtext[decryptedtext_len] = '\0'; // 添加字符串结束符
    printf("Decrypted text: %s\n", decryptedtext); // 打印解密后的明文

    return 0; // 程序正常结束
}
